package tp.pr4.instructions;

import tp.pr4.Message;
import tp.pr4.NavigationModule;
import tp.pr4.RobotEngine;
import tp.pr4.instructions.exceptions.InstructionExecutionException;
import tp.pr4.instructions.exceptions.WrongInstructionFormatException;
import tp.pr4.items.ItemContainer;

/**
 * Its execution moves the robot from one place to the next one in the current
 * direction. This instruction works if the user writes MOVE or MOVER
 * 
 */
public class MoveInstruction implements Instruction {

	@Override
	/**
	 * Parses the String returning a MoveInstruction instance or throwing a WrongInstructionFormatException()
	 * @param cad - text String to parse
	 * @returns Instruction Reference to an instance of MoveInstruction
	 * @throws WrongInstructionFormatException - When the String is not MOVE
	 */
	public Instruction parse(String cad) throws WrongInstructionFormatException {
		String[] words = cad.split(" ");
		for (String i : Message.MOVE_INSTRUCTION) {
			if (words[0].equalsIgnoreCase(i))
				return new MoveInstruction();
		}
		throw new WrongInstructionFormatException(Message.NOT_UNDERSTAND);
	} // puede que haya que cambiar el mensaje de la excepcion

	@Override
	/**
	 * Returns a description of the Instruction syntax. The string does not end with the line separator. 
	 * It is up to the caller adding it before printing.
	 * @returns the command syntax MOVE|MOVER
	 */
	public String getHelp() {
		String help = Message.MOVE_INSTRUCTION[0];
		for (int i = 1; i < Message.MOVE_INSTRUCTION.length; i++)
			help += "|" + Message.MOVE_INSTRUCTION[i];

		return help;
	}

	@Override
	/**
	 * Set the execution context. The method receives the entire engine (engine, navigation and the robot container) even though the actual implementation of execute() may not require it.
	 * @param engine - The robot engine
	 * @param navigation - The information about the game, i.e., the places, current direction and current heading to navigate
	 * @param robotContainer - The inventory of the robot
	 */
	public void configureContext(RobotEngine engine,
			NavigationModule navigation, ItemContainer robotContainer) {
		this.engine = engine;
		this.navigation = navigation;
	}

	@Override
	/**
	 * Moves from the current place to the next place on the current Direction. An opened street must exist between both places to be moved
	 * @throws InstructionExecutionException - When the robot cannot go to other place (there is a wall, a closed street...)
	 */
	public void execute() throws InstructionExecutionException {
		try {
			this.navigation.move();
		} catch (InstructionExecutionException e) {
			if (this.navigation.getHeadingStreet() == null)
				throw new InstructionExecutionException(
						Message.NO_STREET.replace("<dir>", this.navigation
								.getCurrentHeading().toString()));
			else if (!this.navigation.getHeadingStreet().isOpen())
				throw new InstructionExecutionException(Message.CLOSED_STREET);
		}
		System.out.println(Message.MOVING.replace("<dir>", this.navigation
				.getCurrentHeading().toString()));
		this.engine.addFuel(-5);
		this.navigation.scanCurrentPlace();
		this.engine.printRobotState();
	}

	private RobotEngine engine;
	private NavigationModule navigation;
}
